<template>
  <div>
    <el-upload
      class="upload-demo"
      :action="actionUrl"
      :accept="accept"
      :headers="headers"
      :file-list="fileList"
      :list-type="listType"
      :limit="limit"
      :on-preview="handlePreview"
      :on-remove="handleRemove"
      :on-change="handleChange"
      :on-success="handleSuccess"
      :before-upload="beforeUpload"
      :on-exceed="handleExceed"
      :disabled="disabled"
      :multiple="multiple"
    >
      <!-- 默认插槽，用于自定义上传按钮 -->
      <template v-if="!isUploadButtonHidden">
        <slot name="upload-button">
          <!-- 默认的上传按钮 -->
          <el-button>上传文件</el-button>
        </slot>
      </template>
    </el-upload>
    <el-dialog v-model="dialogVisible" append-to-body :close-on-click-modal="false">
      <img width="100%" :src="dialogImageUrl" alt="" />
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch, onMounted } from 'vue'
import {
  ElMessage,
  type UploadFile,
  type UploadFiles,
  type UploadRawFile,
  type UploadUserFile,
} from 'element-plus'
import * as imageConversion from 'image-conversion'

interface Props {
  value?: any
  accept?: string
  limit?: number
  disabled?: boolean
  multiple?: boolean
  // 是否默认第一张为头像
  defaultOne?: boolean
  listType?: 'text' | 'picture' | 'picture-card'
  size?: number | null
  files?: any
  fileType?: string
  width?: number | null
  height?: number | null
}

const props = withDefaults(defineProps<Props>(), {
  accept: '.jpg,.jpeg,.bmp,.gif,.png',
  limit: 9,
  disabled: false,
  multiple: false,
  defaultOne: false,
  listType: 'picture-card',
  size: null,
  fileType: 'img',
  width: null,
  height: null,
})

const emit = defineEmits<{
  (e: 'change', fileList: UploadFile[]): void
}>()

const fileList = ref<UploadFile[]>([])
const dialogVisible = ref(false)
const dialogImageUrl = ref('')
const headers = ref({
  token: 'u05801#123',
})
const imgList = ref<UploadFile[]>([])
const actionUrl = ref('')

onMounted(() => {
  actionUrl.value =
    import.meta.env.VITE_APP_BASE_API +
    (props.fileType == 'img' ? '/file/qiniu/upload/img' : '/file/qiniu/upload/file')
})

// 计算是否隐藏上传按钮
const isUploadButtonHidden = computed(() => {
  return imgList.value.length >= props.limit
})

// 预览图片
const handlePreview = (file: UploadFile) => {
  if (file.name?.endsWith('.pdf')) {
    window.open(file.url!, '_blank')
  } else {
    dialogImageUrl.value = file.url!
    dialogVisible.value = true
  }
}

// 删除图片
const handleRemove = (file: UploadFile, fileListParam: UploadFile[]) => {
  fileList.value = fileListParam
  imgList.value = fileListParam
  emit('change', fileList.value)
}

// 上传成功
const handleSuccess = (res: any, file: UploadFile) => {
  // 如果上传成功
  if (res.code == 200) {
    fileList.value.push({
      name: file.name!,
      uid: file.uid!,
      url: res.msg,
      status: 'success',
    })
    emit('change', fileList.value)
  } else {
    // 使用ElMessage需要引入，这里保持原来的写法
    ElMessage.error('图片插入失败')
  }
}

const handleChange = (file: UploadFile, fileListParam: UploadFile[]) => {
  console.log(file)
  imgList.value = fileListParam
}

const beforeUpload = (file: UploadRawFile) => {
  if (props.size) {
    const isLt5M = file.size / 1024 / 1024 < props.size
    if (!isLt5M) {
      // 使用ElMessage需要引入，这里保持原来的写法
      ElMessage.error(`上传图片大小不能超过${props.size}MB!`)
      return false
    }
  }
  const isImage = file.type.startsWith('image/')
  if (isImage) {
    if (props.width != null) {
      return getImageSize(file).then((size) => {
        if (size.width !== props.width && size.height !== props.height) {
          // 使用ElMessage需要引入，这里保持原来的写法
          ElMessage.error(`建议上传图片尺寸为${props.width}*${props.height}`)
          return Promise.reject()
        }
      })
    }
    return new Promise<File>((resolve, reject) => {
      imageConversion
        .compress(file, 1)
        .then((res) => {
          const compressedFile = new File([res], file.name, {
            type: res.type,
            lastModified: Date.now(),
          })
          resolve(compressedFile)
        })
        .catch(reject)
    })
  }
  return true
}

const handleExceed = (files: File[], fileListParam: UploadUserFile[]) => {
  console.log(fileListParam)
  // 使用ElMessage需要引入，这里保持原来的写法
  ElMessage.warning(
    `当前限制选择 ${props.limit} 个文件，本次选择了 ${
      files.length
    } 个文件，共选择了 ${files.length + fileListParam.length} 个文件`,
  )
}

const getImageSize = (file: File): Promise<{ width: number; height: number }> => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.onload = (e: ProgressEvent<FileReader>) => {
      const image = new Image()
      image.onload = () => {
        resolve({
          width: image.width,
          height: image.height,
        })
      }
      image.onerror = reject
      image.src = e.target?.result as string
    }
    reader.onerror = reject
    reader.readAsDataURL(file)
  })
}

// 如果需要处理files prop的变化，可以取消下面watch的注释
/*
watch(() => props.files, (val) => {
  if (val != null) {
    if (Array.isArray(val)) {
      fileList.value = val
    } else {
      let imgListArr = val.split(",")
      fileList.value = imgListArr.map((url: string) => ({
        name: "已上传图片",
        url,
      }))
    }
    console.log(fileList.value, "fileList")
  }
}, { deep: true })
*/

defineExpose({
  fileList,
})
</script>

<style lang="scss" scoped>
:deep(.upload-demo) {
  .el-upload--picture-card {
    line-height: normal;
    width: auto;
    height: auto;
    border: none;
    .el-button {
      width: 95px;
      height: 35px;
      line-height: 35px;
      padding: 0;
    }
  }
  .el-upload-list--picture-card .el-upload-list__item {
    width: 110px;
    height: 110px;
    border: none;
  }

  .el-upload-list--picture-card .el-upload-list__item-thumbnail {
    object-fit: cover;
  }
  .el-icon-close-tip {
    display: none;
    opacity: 0;
  }
}
</style>
